using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.GamePlay;
using LFloatMath.Math;
using NetProtocol.POD;

namespace IQIGame.Onigao.Logic
{
    public enum EBattleUpdateType
    {
        Min,
        StartPart = 1, // 播放timeline
        SkillEffective = 2, // 技能效果 启动 用来判断是否需要根据信号点执行阻断
        BuffChange = 3, // Buff的添加与删除
        AttrChange = 4, // 属性修改
        PosChange = 5, // 位置修改
        Dead = 6, // 死亡
        BuffDamage = 7, // Dot伤害
        Shield = 8, // 护盾
        CustomProperty = 9, // customProperty 改变
        BuffCure = 10, // Buff治疗
        AddSkill = 11, // 添加或删除技能
        WeaknessPoint = 12, // 弱点
        SkillEffectiveStart = 13, // 技能效果结算 需要在内部找小类型返回 对目标
        SkillEffectiveEnd = 14, // 技能效果结算结束 与start对应
        Charge = 15, // 蓄力
        ChargeStop = 16, // 停止蓄力
        Morph = 17, // 修改模型
        Round = 18, // 回合信息
        Turn = 19, // 出手信息
        PermitCast = 20, // 准备释放技能
        CastSkill = 21, // 释放技能
        CastSkillComplete = 22, // 释放技能结束
        Substitute = 23, // 替补
        NextWave = 24, // 下波次
        SkillEffectiveResponse = 25, // 技能效果结算结束 与SkillEffective对应
        RemoveUnit = 26, // 移除单位

        Max
    }

    public class BaseBattleCommand : ISerializeCustomPOD
    {
        public static T Get<T>() where T : BaseBattleCommand, new()
        {
            return new T();
        }

        public virtual void Serialize(SOutputStream _buf)
        {
        }

        public virtual void DeSerialize(SInputStream _buf)
        {
        }

        // 用于做特殊的序列化操作
        protected virtual void OnSerialize(SOutputStream _buf)
        {
        }

        protected virtual void OnDeSerialize(SInputStream _buf)
        {
        }
    }

    public partial class BattleCommand_StartPart : BaseBattleCommand
    {
        public long partGUID;
        public int skillID;
        public int aiMoveType;

        public List<int>[] targetGUID;
    }

    // 多目标只有一个effective
    public partial class BattleCommand_SkillEffective : BaseBattleCommand
    {
        public long part;
        public int index; // 0+
        public int responseGUID;
    }

    // 每个目标都有，与resp成组
    public partial class BattleCommand_SkillEffectiveStart : BaseBattleCommand
    {
        public long targetID;
        public int responseGUID;
        public long partGUID;
        public SkillEffectiveResponse data; // 部分技能会有需要在技能命中前展示的效果 （冲撞
    }

    public partial class BattleCommand_SkillEffectiveEnd : BaseBattleCommand
    {
        public int responseGUID;
        public SkillEffectiveResponse data;
        // public int skillID;
    }

    public partial class BattleCommand_SkillEffectiveResponse : BaseBattleCommand
    {
        public int responseGUID;
    }

    public partial class BattleCommand_BuffChange : BaseBattleCommand
    {
        public int triggerType;
        public BuffData buff;
    }

    public partial class BattleCommand_AttrChange : BaseBattleCommand
    {
        public int attrType;
        public int addType; // EAttributeAddType
        public int value;
        public bool add; // add or Set
    }

    public partial class BattleCommand_PosChange : BaseBattleCommand
    {
        public UpdateVector2 pos;
        public UpdateVector2 forward;
        public List<UpdateVector2> path = new List<UpdateVector2>();
    }

    public partial class BattleCommand_Dead : BaseBattleCommand
    {
        public long attacker;
        public bool relive;
    }

    public partial class BattleCommand_BuffDamage : BaseBattleCommand
    {
        public DamageResponse damage;
    }

    public partial class BattleCommand_BuffCure : BaseBattleCommand
    {
        public CureResponse cure;
    }

    public partial class BattleCommand_Shield : BaseBattleCommand
    {
        public int shield;
    }

    public partial class BattleCommand_CustomProperty : BaseBattleCommand
    {
        public int key;
        public int valueType;
        public TAny value;

        protected override void OnDeSerialize(SInputStream _buf)
        {
            base.OnDeSerialize(_buf);
            this.value = TAnyHelper.NewAny((ETAnyType)this.valueType);
            this.value.DeSerialize(_buf);
        }
    }

    public partial class BattleCommand_AddSkill : BaseBattleCommand
    {
        public int skillID;
        public bool add;
    }

    public partial class BattleCommand_WeaknessPoint : BaseBattleCommand
    {
        public int point;
    }

    public partial class BattleCommand_Charge : BaseBattleCommand
    {
        public int duration;
        public int castSkillID;
        public UpdateVector2 pos;
        public UpdateVector2 aspect;
        public int curSkill;
        public string chargePrefab;
        public byte[] targetSelectConfig;
    }

    public partial class BattleCommand_ChargeStop : BaseBattleCommand
    {
    }

    public partial class BattleCommand_Morph : BaseBattleCommand
    {
        public string resName;
        public int entityType;
        public bool active;
    }

    public partial class BattleCommand_Round : BaseBattleCommand
    {
        public bool isEnd;
        public int roundNum;
        public List<int> turnQueue;
    }

    public partial class BattleCommand_Turn : BaseBattleCommand
    {
        public bool isEnd;
        public List<int> turnQueue;
    }

    public partial class BattleCommand_PermitCast : BaseBattleCommand
    {
        public int skillID;
    }

    public partial class BattleCommand_CastSkill : BaseBattleCommand
    {
        public int skillID;
        public UpdateVector2 realPos;
        public UpdateVector2 targetPos;
    }

    public partial class BattleCommand_CastSkillComplete : BaseBattleCommand
    {
    }

    public partial class BattleCommand_Substitute : BaseBattleCommand
    {
        public BattleUnitViewPOD subUnit;
        public int teamIndex;
    }

    public partial class BattleCommand_NextWave : BaseBattleCommand
    {
        public BattleTeamViewPOD team;
    }

    public partial class BattleCommand_RemoveUnit : BaseBattleCommand
    {
    }

    public class UpdateVector2 : ISerializeCustomPOD
    {
        private long x;
        private long y;

        public void Serialize(SOutputStream _buf)
        {
            _buf.Write_long(x);
            _buf.Write_long(y);
        }

        public void DeSerialize(SInputStream _buf)
        {
            this.x = _buf.Read_long();
            this.y = _buf.Read_long();
        }

        public LVector2 ToLVector()
        {
            return new LVector2(new LFloat(true, this.x), new LFloat(true, this.y));
        }

        public static UpdateVector2 Create(LVector2 v2)
        {
            var rV2 = new UpdateVector2()
            {
                x = v2.x._val,
                y = v2.y._val
            };
            return rV2;
        }
    }
}